"""
冲突解决器

负责识别、分析和解决多智能体系统中的冲突。
"""

from typing import Dict, List, Any, Optional, Tuple, Set
from datetime import datetime, timedelta
from enum import Enum
from dataclasses import dataclass
import asyncio

from ..agents.base_agent import BaseAgent, Message, Task, TaskPriority
from ..agents.agent_roles import AgentRole, AgentLevel


class ConflictType(Enum):
    """冲突类型"""
    RESOURCE_CONFLICT = "resource_conflict"         # 资源冲突
    PRIORITY_CONFLICT = "priority_conflict"         # 优先级冲突
    DECISION_CONFLICT = "decision_conflict"         # 决策冲突
    TIMING_CONFLICT = "timing_conflict"             # 时间冲突
    AUTHORITY_CONFLICT = "authority_conflict"       # 权限冲突
    DATA_CONFLICT = "data_conflict"                 # 数据冲突
    STRATEGY_CONFLICT = "strategy_conflict"         # 策略冲突


class ConflictSeverity(Enum):
    """冲突严重程度"""
    LOW = "low"                 # 低
    MEDIUM = "medium"           # 中
    HIGH = "high"               # 高
    CRITICAL = "critical"       # 关键


class ResolutionStrategy(Enum):
    """解决策略"""
    ESCALATION = "escalation"               # 升级
    NEGOTIATION = "negotiation"             # 协商
    VOTING = "voting"                       # 投票
    ARBITRATION = "arbitration"             # 仲裁
    PRIORITY_BASED = "priority_based"       # 基于优先级
    RESOURCE_ALLOCATION = "resource_allocation"  # 资源分配
    TIME_SLICING = "time_slicing"           # 时间分片


@dataclass
class ConflictRecord:
    """冲突记录"""
    conflict_id: str
    conflict_type: ConflictType
    severity: ConflictSeverity
    involved_agents: List[str]
    conflict_data: Dict[str, Any]
    detected_at: datetime
    resolution_strategy: Optional[ResolutionStrategy] = None
    resolution_steps: List[Dict[str, Any]] = None
    resolved_at: Optional[datetime] = None
    resolution_success: Optional[bool] = None
    resolution_notes: Optional[str] = None
    
    def __post_init__(self):
        if self.resolution_steps is None:
            self.resolution_steps = []


class ConflictResolver:
    """冲突解决器"""
    
    def __init__(self):
        """初始化冲突解决器"""
        # 活跃冲突
        self.active_conflicts: Dict[str, ConflictRecord] = {}
        
        # 冲突历史
        self.conflict_history: List[ConflictRecord] = []
        
        # 解决策略映射
        self.strategy_mapping = self._initialize_strategy_mapping()
        
        # 权限层级
        self.authority_hierarchy = {
            AgentLevel.STRATEGIC: 3,
            AgentLevel.MANAGEMENT: 2,
            AgentLevel.OPERATIONAL: 1
        }
        
        # 配置参数
        self.config = {
            "max_resolution_time": timedelta(hours=2),
            "escalation_timeout": timedelta(minutes=30),
            "negotiation_rounds": 3,
            "voting_timeout": timedelta(minutes=15),
            "auto_escalation_threshold": ConflictSeverity.HIGH
        }
        
        # 性能指标
        self.metrics = {
            "total_conflicts": 0,
            "resolved_conflicts": 0,
            "escalated_conflicts": 0,
            "average_resolution_time": 0.0,
            "resolution_success_rate": 0.0,
            "conflict_type_distribution": {},
            "strategy_effectiveness": {}
        }
    
    async def detect_conflict(
        self,
        agents: List[BaseAgent],
        context: Dict[str, Any]
    ) -> Optional[ConflictRecord]:
        """
        检测冲突
        
        Args:
            agents: 涉及的智能体
            context: 上下文信息
            
        Returns:
            冲突记录（如果检测到冲突）
        """
        try:
            # 检测各种类型的冲突
            conflicts = []
            
            # 资源冲突检测
            resource_conflict = self._detect_resource_conflict(agents, context)
            if resource_conflict:
                conflicts.append(resource_conflict)
            
            # 优先级冲突检测
            priority_conflict = self._detect_priority_conflict(agents, context)
            if priority_conflict:
                conflicts.append(priority_conflict)
            
            # 决策冲突检测
            decision_conflict = self._detect_decision_conflict(agents, context)
            if decision_conflict:
                conflicts.append(decision_conflict)
            
            # 时间冲突检测
            timing_conflict = self._detect_timing_conflict(agents, context)
            if timing_conflict:
                conflicts.append(timing_conflict)
            
            # 权限冲突检测
            authority_conflict = self._detect_authority_conflict(agents, context)
            if authority_conflict:
                conflicts.append(authority_conflict)
            
            # 返回最严重的冲突
            if conflicts:
                return max(conflicts, key=lambda c: c.severity.value)
            
            return None
            
        except Exception as e:
            return None
    
    async def resolve_conflict(
        self,
        conflict_id: str,
        involved_agents: List[str],
        conflict_data: Dict[str, Any]
    ) -> bool:
        """
        解决冲突
        
        Args:
            conflict_id: 冲突ID
            involved_agents: 涉及的智能体ID列表
            conflict_data: 冲突数据
            
        Returns:
            解决是否成功
        """
        try:
            # 创建冲突记录
            conflict_record = ConflictRecord(
                conflict_id=conflict_id,
                conflict_type=ConflictType(conflict_data.get("type", "resource_conflict")),
                severity=ConflictSeverity(conflict_data.get("severity", "medium")),
                involved_agents=involved_agents,
                conflict_data=conflict_data,
                detected_at=datetime.now()
            )
            
            # 添加到活跃冲突
            self.active_conflicts[conflict_id] = conflict_record
            
            # 选择解决策略
            strategy = self._select_resolution_strategy(conflict_record)
            conflict_record.resolution_strategy = strategy
            
            # 执行解决策略
            success = await self._execute_resolution_strategy(conflict_record)
            
            # 更新冲突记录
            conflict_record.resolved_at = datetime.now()
            conflict_record.resolution_success = success
            
            # 移动到历史记录
            self.conflict_history.append(conflict_record)
            del self.active_conflicts[conflict_id]
            
            # 更新指标
            self._update_metrics(conflict_record)
            
            return success
            
        except Exception as e:
            return False
    
    def _detect_resource_conflict(
        self,
        agents: List[BaseAgent],
        context: Dict[str, Any]
    ) -> Optional[ConflictRecord]:
        """检测资源冲突"""
        # 检查是否有多个智能体竞争相同资源
        resource_requests = {}
        
        for agent in agents:
            # 简化的资源需求检查
            if hasattr(agent, 'current_task') and agent.current_task:
                task_resources = agent.current_task.data.get("required_resources", [])
                for resource in task_resources:
                    if resource not in resource_requests:
                        resource_requests[resource] = []
                    resource_requests[resource].append(agent.agent_id)
        
        # 检查是否有资源被多个智能体请求
        for resource, requesters in resource_requests.items():
            if len(requesters) > 1:
                return ConflictRecord(
                    conflict_id=f"resource_conflict_{datetime.now().timestamp()}",
                    conflict_type=ConflictType.RESOURCE_CONFLICT,
                    severity=ConflictSeverity.MEDIUM,
                    involved_agents=requesters,
                    conflict_data={
                        "resource": resource,
                        "requesters": requesters,
                        "context": context
                    },
                    detected_at=datetime.now()
                )
        
        return None
    
    def _detect_priority_conflict(
        self,
        agents: List[BaseAgent],
        context: Dict[str, Any]
    ) -> Optional[ConflictRecord]:
        """检测优先级冲突"""
        # 检查是否有相同优先级的冲突任务
        priority_tasks = {}
        
        for agent in agents:
            if hasattr(agent, 'task_queue'):
                for task in agent.task_queue:
                    priority = task.priority
                    if priority not in priority_tasks:
                        priority_tasks[priority] = []
                    priority_tasks[priority].append((agent.agent_id, task))
        
        # 检查关键优先级任务是否过多
        if TaskPriority.CRITICAL in priority_tasks:
            critical_tasks = priority_tasks[TaskPriority.CRITICAL]
            if len(critical_tasks) > 3:  # 阈值
                return ConflictRecord(
                    conflict_id=f"priority_conflict_{datetime.now().timestamp()}",
                    conflict_type=ConflictType.PRIORITY_CONFLICT,
                    severity=ConflictSeverity.HIGH,
                    involved_agents=[agent_id for agent_id, _ in critical_tasks],
                    conflict_data={
                        "critical_tasks": critical_tasks,
                        "context": context
                    },
                    detected_at=datetime.now()
                )
        
        return None
    
    def _detect_decision_conflict(
        self,
        agents: List[BaseAgent],
        context: Dict[str, Any]
    ) -> Optional[ConflictRecord]:
        """检测决策冲突"""
        # 检查是否有相互矛盾的决策
        decisions = context.get("decisions", {})
        
        if len(decisions) > 1:
            # 简化的决策冲突检测
            decision_values = list(decisions.values())
            if len(set(decision_values)) > 1:  # 有不同的决策
                return ConflictRecord(
                    conflict_id=f"decision_conflict_{datetime.now().timestamp()}",
                    conflict_type=ConflictType.DECISION_CONFLICT,
                    severity=ConflictSeverity.MEDIUM,
                    involved_agents=[agent.agent_id for agent in agents],
                    conflict_data={
                        "decisions": decisions,
                        "context": context
                    },
                    detected_at=datetime.now()
                )
        
        return None
    
    def _detect_timing_conflict(
        self,
        agents: List[BaseAgent],
        context: Dict[str, Any]
    ) -> Optional[ConflictRecord]:
        """检测时间冲突"""
        # 检查是否有时间冲突的任务
        scheduled_tasks = []
        
        for agent in agents:
            if hasattr(agent, 'task_queue'):
                for task in agent.task_queue:
                    if "deadline" in task.data:
                        scheduled_tasks.append((agent.agent_id, task))
        
        # 检查是否有重叠的紧急任务
        urgent_tasks = [
            (agent_id, task) for agent_id, task in scheduled_tasks
            if task.priority == TaskPriority.CRITICAL
        ]
        
        if len(urgent_tasks) > 2:
            return ConflictRecord(
                conflict_id=f"timing_conflict_{datetime.now().timestamp()}",
                conflict_type=ConflictType.TIMING_CONFLICT,
                severity=ConflictSeverity.HIGH,
                involved_agents=[agent_id for agent_id, _ in urgent_tasks],
                conflict_data={
                    "urgent_tasks": urgent_tasks,
                    "context": context
                },
                detected_at=datetime.now()
            )
        
        return None
    
    def _detect_authority_conflict(
        self,
        agents: List[BaseAgent],
        context: Dict[str, Any]
    ) -> Optional[ConflictRecord]:
        """检测权限冲突"""
        # 检查是否有权限级别冲突
        authority_levels = {}
        
        for agent in agents:
            level = getattr(agent, 'level', AgentLevel.OPERATIONAL)
            if level not in authority_levels:
                authority_levels[level] = []
            authority_levels[level].append(agent.agent_id)
        
        # 检查是否有跨级别的决策冲突
        if len(authority_levels) > 1 and "decision_required" in context:
            return ConflictRecord(
                conflict_id=f"authority_conflict_{datetime.now().timestamp()}",
                conflict_type=ConflictType.AUTHORITY_CONFLICT,
                severity=ConflictSeverity.MEDIUM,
                involved_agents=[agent.agent_id for agent in agents],
                conflict_data={
                    "authority_levels": authority_levels,
                    "context": context
                },
                detected_at=datetime.now()
            )
        
        return None
    
    def _select_resolution_strategy(self, conflict_record: ConflictRecord) -> ResolutionStrategy:
        """选择解决策略"""
        conflict_type = conflict_record.conflict_type
        severity = conflict_record.severity
        
        # 基于冲突类型和严重程度选择策略
        strategy_map = self.strategy_mapping.get(conflict_type, {})
        
        if severity == ConflictSeverity.CRITICAL:
            return strategy_map.get("critical", ResolutionStrategy.ESCALATION)
        elif severity == ConflictSeverity.HIGH:
            return strategy_map.get("high", ResolutionStrategy.ARBITRATION)
        elif severity == ConflictSeverity.MEDIUM:
            return strategy_map.get("medium", ResolutionStrategy.NEGOTIATION)
        else:
            return strategy_map.get("low", ResolutionStrategy.PRIORITY_BASED)
    
    async def _execute_resolution_strategy(self, conflict_record: ConflictRecord) -> bool:
        """执行解决策略"""
        strategy = conflict_record.resolution_strategy
        
        try:
            if strategy == ResolutionStrategy.ESCALATION:
                return await self._execute_escalation(conflict_record)
            elif strategy == ResolutionStrategy.NEGOTIATION:
                return await self._execute_negotiation(conflict_record)
            elif strategy == ResolutionStrategy.VOTING:
                return await self._execute_voting(conflict_record)
            elif strategy == ResolutionStrategy.ARBITRATION:
                return await self._execute_arbitration(conflict_record)
            elif strategy == ResolutionStrategy.PRIORITY_BASED:
                return await self._execute_priority_based(conflict_record)
            elif strategy == ResolutionStrategy.RESOURCE_ALLOCATION:
                return await self._execute_resource_allocation(conflict_record)
            elif strategy == ResolutionStrategy.TIME_SLICING:
                return await self._execute_time_slicing(conflict_record)
            else:
                return False
        except Exception as e:
            conflict_record.resolution_notes = f"策略执行失败: {e}"
            return False
    
    async def _execute_escalation(self, conflict_record: ConflictRecord) -> bool:
        """执行升级策略"""
        conflict_record.resolution_steps.append({
            "step": "escalation",
            "timestamp": datetime.now(),
            "action": "escalate_to_higher_authority",
            "details": "将冲突升级到更高权限级别处理"
        })
        
        # 模拟升级过程
        await asyncio.sleep(0.1)
        
        conflict_record.resolution_notes = "冲突已升级到战略层处理"
        return True
    
    async def _execute_negotiation(self, conflict_record: ConflictRecord) -> bool:
        """执行协商策略"""
        max_rounds = self.config["negotiation_rounds"]
        
        for round_num in range(max_rounds):
            conflict_record.resolution_steps.append({
                "step": f"negotiation_round_{round_num + 1}",
                "timestamp": datetime.now(),
                "action": "conduct_negotiation",
                "details": f"进行第{round_num + 1}轮协商"
            })
            
            # 模拟协商过程
            await asyncio.sleep(0.1)
            
            # 简化的协商成功判断
            if round_num >= 1:  # 假设第2轮协商成功
                conflict_record.resolution_notes = f"经过{round_num + 1}轮协商达成一致"
                return True
        
        conflict_record.resolution_notes = "协商失败，需要其他解决方案"
        return False
    
    async def _execute_voting(self, conflict_record: ConflictRecord) -> bool:
        """执行投票策略"""
        conflict_record.resolution_steps.append({
            "step": "voting",
            "timestamp": datetime.now(),
            "action": "initiate_voting",
            "details": "发起投票解决冲突"
        })
        
        # 模拟投票过程
        await asyncio.sleep(0.1)
        
        # 简化的投票结果
        involved_count = len(conflict_record.involved_agents)
        majority_threshold = involved_count // 2 + 1
        
        # 假设投票成功
        conflict_record.resolution_notes = f"投票通过，{majority_threshold}/{involved_count}同意"
        return True
    
    async def _execute_arbitration(self, conflict_record: ConflictRecord) -> bool:
        """执行仲裁策略"""
        conflict_record.resolution_steps.append({
            "step": "arbitration",
            "timestamp": datetime.now(),
            "action": "assign_arbitrator",
            "details": "指定仲裁者解决冲突"
        })
        
        # 模拟仲裁过程
        await asyncio.sleep(0.1)
        
        conflict_record.resolution_notes = "仲裁完成，冲突已解决"
        return True
    
    async def _execute_priority_based(self, conflict_record: ConflictRecord) -> bool:
        """执行基于优先级的策略"""
        conflict_record.resolution_steps.append({
            "step": "priority_resolution",
            "timestamp": datetime.now(),
            "action": "apply_priority_rules",
            "details": "根据优先级规则解决冲突"
        })
        
        # 模拟优先级处理
        await asyncio.sleep(0.1)
        
        conflict_record.resolution_notes = "根据优先级规则分配资源"
        return True
    
    async def _execute_resource_allocation(self, conflict_record: ConflictRecord) -> bool:
        """执行资源分配策略"""
        conflict_record.resolution_steps.append({
            "step": "resource_allocation",
            "timestamp": datetime.now(),
            "action": "reallocate_resources",
            "details": "重新分配资源解决冲突"
        })
        
        # 模拟资源分配
        await asyncio.sleep(0.1)
        
        conflict_record.resolution_notes = "资源重新分配完成"
        return True
    
    async def _execute_time_slicing(self, conflict_record: ConflictRecord) -> bool:
        """执行时间分片策略"""
        conflict_record.resolution_steps.append({
            "step": "time_slicing",
            "timestamp": datetime.now(),
            "action": "schedule_time_slots",
            "details": "分配时间片解决冲突"
        })
        
        # 模拟时间分片
        await asyncio.sleep(0.1)
        
        conflict_record.resolution_notes = "时间片分配完成"
        return True
    
    def _initialize_strategy_mapping(self) -> Dict[ConflictType, Dict[str, ResolutionStrategy]]:
        """初始化策略映射"""
        return {
            ConflictType.RESOURCE_CONFLICT: {
                "critical": ResolutionStrategy.ESCALATION,
                "high": ResolutionStrategy.RESOURCE_ALLOCATION,
                "medium": ResolutionStrategy.NEGOTIATION,
                "low": ResolutionStrategy.PRIORITY_BASED
            },
            ConflictType.PRIORITY_CONFLICT: {
                "critical": ResolutionStrategy.ESCALATION,
                "high": ResolutionStrategy.ARBITRATION,
                "medium": ResolutionStrategy.PRIORITY_BASED,
                "low": ResolutionStrategy.NEGOTIATION
            },
            ConflictType.DECISION_CONFLICT: {
                "critical": ResolutionStrategy.ESCALATION,
                "high": ResolutionStrategy.VOTING,
                "medium": ResolutionStrategy.NEGOTIATION,
                "low": ResolutionStrategy.ARBITRATION
            },
            ConflictType.TIMING_CONFLICT: {
                "critical": ResolutionStrategy.ESCALATION,
                "high": ResolutionStrategy.TIME_SLICING,
                "medium": ResolutionStrategy.PRIORITY_BASED,
                "low": ResolutionStrategy.NEGOTIATION
            },
            ConflictType.AUTHORITY_CONFLICT: {
                "critical": ResolutionStrategy.ESCALATION,
                "high": ResolutionStrategy.ESCALATION,
                "medium": ResolutionStrategy.ARBITRATION,
                "low": ResolutionStrategy.NEGOTIATION
            }
        }
    
    def _update_metrics(self, conflict_record: ConflictRecord):
        """更新指标"""
        self.metrics["total_conflicts"] += 1
        
        if conflict_record.resolution_success:
            self.metrics["resolved_conflicts"] += 1
        
        if conflict_record.resolution_strategy == ResolutionStrategy.ESCALATION:
            self.metrics["escalated_conflicts"] += 1
        
        # 更新解决时间
        if conflict_record.resolved_at:
            resolution_time = (
                conflict_record.resolved_at - conflict_record.detected_at
            ).total_seconds()
            
            total = self.metrics["total_conflicts"]
            current_avg = self.metrics["average_resolution_time"]
            self.metrics["average_resolution_time"] = (
                (current_avg * (total - 1) + resolution_time) / total
            )
        
        # 更新成功率
        total = self.metrics["total_conflicts"]
        resolved = self.metrics["resolved_conflicts"]
        self.metrics["resolution_success_rate"] = resolved / total if total > 0 else 0
        
        # 更新冲突类型分布
        conflict_type = conflict_record.conflict_type.value
        if conflict_type not in self.metrics["conflict_type_distribution"]:
            self.metrics["conflict_type_distribution"][conflict_type] = 0
        self.metrics["conflict_type_distribution"][conflict_type] += 1
        
        # 更新策略有效性
        if conflict_record.resolution_strategy:
            strategy = conflict_record.resolution_strategy.value
            if strategy not in self.metrics["strategy_effectiveness"]:
                self.metrics["strategy_effectiveness"][strategy] = {"total": 0, "success": 0}
            
            self.metrics["strategy_effectiveness"][strategy]["total"] += 1
            if conflict_record.resolution_success:
                self.metrics["strategy_effectiveness"][strategy]["success"] += 1
    
    def get_conflict_status(self) -> Dict[str, Any]:
        """获取冲突状态"""
        return {
            "active_conflicts": len(self.active_conflicts),
            "total_conflicts_resolved": len(self.conflict_history),
            "metrics": self.metrics,
            "active_conflict_details": [
                {
                    "conflict_id": conflict.conflict_id,
                    "type": conflict.conflict_type.value,
                    "severity": conflict.severity.value,
                    "involved_agents": conflict.involved_agents,
                    "detected_at": conflict.detected_at.isoformat(),
                    "strategy": conflict.resolution_strategy.value if conflict.resolution_strategy else None
                }
                for conflict in self.active_conflicts.values()
            ]
        }
    
    def get_conflict_history(
        self,
        conflict_type: Optional[ConflictType] = None,
        limit: Optional[int] = None
    ) -> List[ConflictRecord]:
        """获取冲突历史"""
        history = self.conflict_history
        
        if conflict_type:
            history = [c for c in history if c.conflict_type == conflict_type]
        
        if limit:
            history = history[-limit:]
        
        return history